import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form';
import type { NamePath } from 'ant-design-vue/lib/form/interface';
import type { DynamicProps } from '#/utils';
import { getDynamicProps } from '../utils/utils';
import { error } from '@/utils/log';

type Props = Partial<DynamicProps<FormProps>>;

export function useForm(props?: Props) {

    const formRef = ref<Nullable<FormActionType>>(null);
    const loadedRef = ref<Nullable<boolean>>(false);

    /**
     * 注册表单操作实例
     * @param instance 表单操作实例对象
     */
    function register(instance: FormActionType) {

        //离开页面时，销毁表单实例
        onUnmounted(() => {
            formRef.value = null;
            loadedRef.value = false;
        });

        if (unref(loadedRef) && instance === unref(formRef)) return;

        formRef.value = instance || null;
        loadedRef.value = true;

        watch(() => props, () => {
            props && instance && instance.setProps(getDynamicProps(props));
        },{
            immediate: true,
            deep: true,
        });
    };

    async function getForm() {
        const form = unref(formRef);
        if (!form) {
            error('表单实例尚未获取，请确保在执行表单操作时已呈现表单！');
        }
        await nextTick();
        return form as FormActionType;
    }

    // 抛出表单操作方法
    const methods: FormActionType = {
        setProps: async (formProps: Partial<FormProps>) => {
            const form = await getForm();
            form.setProps(formProps);
        },

        scrollToField: async (name: NamePath, options?: ScrollOptions | undefined) => {

        },

        updateSchema: async (data: Partial<FormSchema> | Partial<FormSchema>[]) => {
            const form = await getForm();
            form.updateSchema(data);
        },
    
        resetSchema: async (data: Partial<FormSchema> | Partial<FormSchema>[]) => {
            const form = await getForm();
            form.resetSchema(data);
        },
    
        clearValidate: async (name?: string | string[]) => {
            const form = await getForm();
            form.clearValidate(name);
        },
    
        resetFields: async () => {
            getForm().then(async (form) => {
                await form.resetFields();
            });
        },
    
        removeSchemaByField: async (field: string | string[]) => {
            unref(formRef)?.removeSchemaByField(field);
        },
    
        // TODO promisify
        getFieldsValue: <T>() => {
            return unref(formRef)?.getFieldsValue() as T;
        },
    
        setFieldsValue: async (values: Recordable<any>) => {
            const form = await getForm();
            form.setFieldsValue(values);
        },
    
        appendSchemaByField: async (
            schema: FormSchema,
            prefixField: string | undefined,
            first: boolean | undefined,
        ) => {
            const form = await getForm();
            form.appendSchemaByField(schema, prefixField, first);
        },
    
        validate: async (nameList?: NamePath[]): Promise<Recordable> => {
            const form = await getForm();
            return form.validate(nameList);
        },
    
        validateFields: async (nameList?: NamePath[]): Promise<Recordable> => {
            const form = await getForm();
            return form.validateFields(nameList);
        },

        // 按需重置表单方法(传入对应的表单字段进行重置。未传入的不做重置处理)
        needsResetFields: async function (name?: string[]): Promise<void> {
            const form = await getForm();
            await form.needsResetFields(name);
        },
    };

    return [register, (methods as any)];
};